/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package PhysicCollection;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;

/**
 *
 * @author Mr.D
 */
public class ReflectPanel extends JPanel implements MouseListener, MouseMotionListener{

    //for mirror
    private int mirror_line_a, mirror_line_b, mirror_line_c;
    private int mirror_point1_posx, mirror_point1_posy, mirror_point2_posx, mirror_point2_posy;

    //for original line
    private int original_line_a, original_line_b, original_line_c;
    private int original_line_point1_posx, original_line_point1_posy, original_line_point2_posx, original_line_point2_posy;
    private int original_vector_x, original_vector_y;
    private boolean is_reflecting;

    //for reflect line
    private int reflect_point_x, reflect_point_y;
    private int reflect_vector_x, reflect_vector_y;

    //for intersection point
    private int intersection_point_x, intersection_point_y;

    //for normal vector
    private int normal_line_a, normal_line_b, normal_line_c;        
    private int normal_vector1_x, normal_vector1_y, normal_vector2_x, normal_vector2_y;
    private int normal_vector_point1_posx, normal_vector_point1_posy, normal_vector_point2_posx, normal_vector_point2_posy;

    //for  parallel line
    private int intersection_normal_parallel_x, intersection_normal_parallel_y;
    private int parallel_line_a, parallel_line_b, parallel_line_c;
    


    //trigger to draw
    private boolean is_drawing_mirror;

    //use to debug
    private int dubug_string_pos_x = 5;
    private int dubug_string_pos_y = 0;
    private int debug_string_line_height = 15;
    
    public ReflectPanel(){
        mirror_point1_posx = mirror_point1_posy = mirror_point2_posx = mirror_point2_posy = -1;
        original_line_point1_posx = original_line_point1_posy = original_line_point2_posx = original_line_point2_posy = -1;
        intersection_point_x = intersection_point_y = -1;
        is_drawing_mirror = false;
        is_reflecting = false;
    }
    @Override
    public void paint(Graphics g){
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.BLACK);
//        g.drawLine(mouseposx, mouseposy, mirrorposx, mirrorposy);
        g.setColor(Color.CYAN);
//        g.drawLine(mirrorposx, mirrorposy, reflectposx, reflectposy);
        g.setColor(Color.YELLOW);
//        g.drawLine(mirrorposx ,mirrorposy, mirrorposx, mouseposy);

        if((mirror_point1_posx != -1)&&(original_line_point1_posx != -1)&&(((mirror_point1_posx != mirror_point2_posx)&&(mirror_point1_posy != mirror_point2_posy))||((original_line_point1_posx != original_line_point2_posx)&&(original_line_point1_posy != original_line_point2_posy)))){
            g.setColor(Color.GRAY);
            g.drawLine(intersection_point_x, 0, intersection_point_x, getHeight());
            g.drawLine(0, intersection_point_y, getWidth(), intersection_point_y);
        }
        
        g.setColor(Color.RED);
        g.drawLine(mirror_point1_posx, mirror_point1_posy, mirror_point2_posx, mirror_point2_posy);       
                
        g.setColor(Color.WHITE);
        g.drawString("Original Point 1(" + original_line_point1_posx + ", "+ original_line_point1_posy+")", original_line_point1_posx + 10, original_line_point1_posy + 5);
        g.drawString("Original Point 2(" + original_line_point2_posx + ", "+ original_line_point2_posy+")", original_line_point2_posx + 10, original_line_point2_posy + 5);
        g.drawString("Mirror Point 1(" + mirror_point1_posx + ", "+ mirror_point1_posy+")", mirror_point1_posx + 10, mirror_point1_posy + 5);
        g.drawString("Mirror Point 2(" + mirror_point2_posx + ", "+ mirror_point2_posy+")", mirror_point2_posx + 10, mirror_point2_posy + 5);
       if((((intersection_point_x > original_line_point1_posx)&&(intersection_point_x < original_line_point2_posx))||((intersection_point_x < original_line_point1_posx)&&(intersection_point_x > original_line_point2_posx)))
            &&(((intersection_point_y > original_line_point1_posy)&&(intersection_point_y < original_line_point2_posy))||((intersection_point_y < original_line_point1_posy)&&(intersection_point_y > original_line_point2_posy)))
                &&(((intersection_point_x > mirror_point1_posx)&&(intersection_point_x < mirror_point2_posx))||((intersection_point_x < mirror_point1_posx)&&(intersection_point_x > mirror_point2_posx)))
                    &&(((intersection_point_y > mirror_point1_posy)&&(intersection_point_y < mirror_point2_posy))||((intersection_point_y < mirror_point1_posy)&&(intersection_point_y > mirror_point2_posy)))){
                        g.setColor(Color.BLUE);
                        g.drawLine(original_line_point1_posx, original_line_point1_posy, intersection_point_x, intersection_point_y);
                        g.setColor(Color.GREEN);
                        g.drawLine(intersection_point_x, intersection_point_y, original_line_point2_posx, original_line_point2_posy);
                        if(is_reflecting){
                            g.setColor(Color.BLUE);
                            g.drawLine(intersection_point_x, intersection_point_y, reflect_point_x, reflect_point_y);
                            //draw final result
                            g.drawLine(intersection_point_x, intersection_point_y, reflect_point_x, reflect_point_y);
                            
                            g.setColor(Color.YELLOW);
                            g.drawLine(intersection_point_x, intersection_point_y, normal_vector_point1_posx, normal_vector_point1_posy);
                            g.setColor(Color.CYAN);
                            g.drawLine(intersection_point_x, intersection_point_y, normal_vector_point2_posx, normal_vector_point2_posy);
                            g.setColor(Color.WHITE);                            
                            g.drawString("Intersection Point(" + intersection_point_x + ", "+ intersection_point_y+")", intersection_point_x + 10, intersection_point_y + 5);
                            g.drawString("Normal Vector Point 1(" + normal_vector_point1_posx + ", "+ normal_vector_point1_posy+")", normal_vector_point1_posx + 10, normal_vector_point1_posy + 5);
                            g.drawString("Normal Vector Point 2(" + normal_vector_point2_posx + ", "+ normal_vector_point2_posy+")", normal_vector_point2_posx + 10, normal_vector_point2_posy + 5);
                            g.drawString("Reflect Point(" + reflect_point_x + ", "+ reflect_point_y+")", reflect_point_x + 10, reflect_point_y + 5);
                        }
                        is_reflecting = true;
       }else{
           g.setColor(Color.BLUE);
           g.drawLine(original_line_point1_posx, original_line_point1_posy, original_line_point2_posx, original_line_point2_posy);
           is_reflecting = false;
       }
       dubug_string_pos_y =0;
       g.setColor(Color.BLACK);
       g.drawString("Intersection Point(" + intersection_point_x + ", "+ intersection_point_y + ")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Original Vector(" + original_vector_x + ", "+ original_vector_y + ")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Normal Vector1(" + normal_vector1_x + ", "+ normal_vector1_y + ")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Normal Vector2(" + normal_vector2_x + ", "+ normal_vector2_y + ")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Normal Vector Point 1(" + normal_vector_point1_posx + ", "+ normal_vector_point1_posy + ")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Normal Vector Point 2(" + normal_vector_point2_posx + ", "+ normal_vector_point2_posy + ")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Reflect Vector(" + reflect_vector_x + ", "+ reflect_vector_y+") (not use now)", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Reflect Point(" + reflect_point_x + ", "+ reflect_point_y+")", dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Original Line Function: " + original_line_a + "x + " + original_line_b + "y + " + original_line_c, dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);
       g.drawString("Mirror Line Function: " + mirror_line_a + "x + " + mirror_line_b + "y + " + mirror_line_c, dubug_string_pos_x, dubug_string_pos_y += debug_string_line_height);       


        
    }

    public void init(){        
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    private void Create_Mirror_Line_Funtion(int point1_posx, int point1_posy, int point2_posx, int point2_posy){
        mirror_line_a = (point2_posy - point1_posy);
        mirror_line_b = (-1)*(point2_posx - point1_posx);
        mirror_line_c = ((-1)*(point2_posy - point1_posy)*(point1_posx) + (point2_posx - point1_posx)*point1_posy);
    }
    private void Create_Original_Line_Funtion(int point1_posx, int point1_posy, int point2_posx, int point2_posy){
        original_line_a = (point2_posy - point1_posy);
        original_line_b = (-1)*(point2_posx - point1_posx);
        original_line_c = ((-1)*(point2_posy - point1_posy)*(point1_posx) + (point2_posx - point1_posx)*point1_posy);
    }
    private void Create_Normal_Line_Function(int point1_posx, int point1_posy, int direction_vector_a, int direction_vector_b){
        normal_line_a = direction_vector_b;
        normal_line_b = (-1)*direction_vector_a;
        normal_line_c = ((-1)*direction_vector_b*(point1_posx) + direction_vector_a*point1_posy);
    }
     private void Create_Parallel_Line_Function(int point1_posx, int point1_posy, int direction_vector_a, int direction_vector_b){
        parallel_line_a = direction_vector_b;
        parallel_line_b = (-1)*direction_vector_a;
        parallel_line_c = ((-1)*direction_vector_b*(point1_posx) + direction_vector_a*point1_posy);
    }
 
    private int Intersection_X(int line1a, int line1b, int line1c, int line2a, int line2b, int line2c){
        int returnx = 0;
        if((line2b*line1a - line1b*line2a) != 0)
            returnx = ((line1b*line2c - line2b*line1c)/(line2b*line1a - line1b*line2a));
//        else
//            intersection_point_x = ((line1b*line2c - line2b*line1c)/1);
        return returnx;
    }
    private int Intersection_Y(int line1a, int line1b, int line1c, int line2a, int line2b, int line2c){
        int returny = 0;
        if((line2a*line1b - line1a*line2b) != 0)
            returny = ((line1a*line2c - line2a*line1c)/(line2a*line1b - line1a*line2b));
//        else
//            intersection_point_x = ((line1b*line2c - line2b*line1c)/1);
        return returny;
    }

//    private int Calculate_Intersection_X(int line_param_a, int line_param_b, int line_param_c, int posy){
//        int returnx = 0;
//        if(line_param_a != 0)
//                returnx = (int)((-1)*line_param_b*posy- line_param_c)/line_param_a;
//        return returnx;
//    }
//
//    private int Calculate_Intersection_Y(int line_param_a, int line_param_b, int line_param_c, int posx){
//        int returny = 0;
//        if(line_param_b != 0)
//            returny = (int)((-1)*line_param_a*posx - line_param_c)/line_param_b;
//        return returny;
//    }

    private int DotProduct(int vector1_x, int vector1_y, int vector2_x, int vector2_y){        
        return ((vector1_x*vector2_x) + (vector1_y * vector2_y));
    }

    private void Calculate_Reflect_Point(){
       //Reflect Function
       //reflect_vector = original_vector - 2*(dotproduct(original_vector, normal_vector))*normal_vector;
       reflect_vector_x = /*original_vector_x - */2*(DotProduct(normal_vector1_x, normal_vector1_y, original_vector_x, original_vector_y)*normal_vector1_x) - original_vector_x;
       reflect_vector_y = /*original_vector_y - */2*(DotProduct(normal_vector1_x, normal_vector1_y, original_vector_x, original_vector_y)*normal_vector1_y) - original_vector_y;
//       Reduce_Reflect_Vector(reflect_vector_x, reflect_vector_y);
       reflect_point_x = reflect_vector_x + intersection_point_x;
       reflect_point_y = reflect_vector_y + intersection_point_y;
    }

    private void Reduce_Reflect_Vector(int original_vector_x, int original_vector_y){
        int abs_smaller_number = (Math.abs(original_vector_y) < Math.abs(original_vector_x))?Math.abs(original_vector_y):Math.abs(original_vector_x);
//        if(Math.abs(original_vector_y) < Math.abs(original_vector_x))
//            abs_smaller_number = Math.abs(original_vector_y);
//        else
//            abs_smaller_number = Math.abs(original_vector_x);
        while(abs_smaller_number > 1){
            if((original_vector_x%abs_smaller_number==0)&&(original_vector_y%abs_smaller_number==0)){
                original_vector_x /= abs_smaller_number;
                original_vector_y /= abs_smaller_number;
                abs_smaller_number = Math.abs(Math.abs(original_vector_y) > Math.abs(original_vector_x) ? original_vector_x : original_vector_y);
//                abs_smaller_number /= abs_smaller_number;
//                abs_smaller_number = Math.abs(abs_smaller_number);
//                break;
//                System.out.println("So lon hon/ So nho hon == " + (original_vector_y < original_vector_x ? original_vector_x : original_vector_y) + ", " + (original_vector_y > original_vector_x ? original_vector_x : original_vector_y));
//                System.out.println("abs_smaller_number == " + abs_smaller_number);
            }else{
                abs_smaller_number --;
            }
//            System.out.println("abs_smaller_number final == " + abs_smaller_number);
        }
        reflect_vector_x = original_vector_x;
        reflect_vector_y = original_vector_y;
//        reflect_point_x = intersection_point_x - reflect_vector_x;
//        reflect_point_y = intersection_point_y - reflect_vector_y;
    }
    
    public void mouseClicked(MouseEvent e) {            

    }

    public void mousePressed(MouseEvent e) {


        if(e.getButton() == MouseEvent.BUTTON3)
            is_drawing_mirror = true;
        else if(e.getButton() == MouseEvent.BUTTON1)
            is_drawing_mirror = false;
        if(is_drawing_mirror){
            mirror_point1_posx = e.getX();
            mirror_point1_posy = e.getY();
            mirror_point2_posx = mirror_point1_posx;
            mirror_point2_posy = mirror_point1_posy;
        }else{
            original_line_point1_posx = e.getX();
            original_line_point1_posy = e.getY();
            original_line_point2_posx = original_line_point1_posx;
            original_line_point2_posy = original_line_point1_posy;
        }
       
        
    }

    public void mouseReleased(MouseEvent e) {        

    }

    public void mouseEntered(MouseEvent e) {

    }

    public void mouseExited(MouseEvent e) {
        
    }

    public void mouseDragged(MouseEvent e) {
       

        if(e.getButton() == MouseEvent.BUTTON3)
                is_drawing_mirror = true;
            else if(e.getButton() == MouseEvent.BUTTON1)
                is_drawing_mirror = false;
        if(is_drawing_mirror){
            mirror_point2_posx = e.getX();
            mirror_point2_posy = e.getY();
            Create_Mirror_Line_Funtion(mirror_point1_posx, mirror_point1_posy, mirror_point2_posx, mirror_point2_posy);            
        }else{
            original_line_point2_posx = e.getX();
            original_line_point2_posy = e.getY();
            Create_Original_Line_Funtion(original_line_point1_posx, original_line_point1_posy, original_line_point2_posx, original_line_point2_posy);
        }
        intersection_point_x = Intersection_X(mirror_line_a, mirror_line_b, mirror_line_c, original_line_a, original_line_b, original_line_c);
        intersection_point_y = Intersection_Y(mirror_line_a, mirror_line_b, mirror_line_c, original_line_a, original_line_b, original_line_c);
        
//        original_vector_x = intersection_point_x - original_line_point1_posx;
//        original_vector_y = intersection_point_y - original_line_point1_posy;
        original_vector_x = original_line_point1_posx - intersection_point_x;
        original_vector_y = -intersection_point_y + original_line_point1_posy;

        normal_vector1_x = mirror_line_a;
        normal_vector1_y = mirror_line_b;
        normal_vector2_x = -mirror_line_a;
        normal_vector2_y = -mirror_line_b;        
        normal_vector_point1_posx = normal_vector1_x + intersection_point_x;
        normal_vector_point1_posy = normal_vector1_y + intersection_point_y;
        normal_vector_point2_posx = normal_vector2_x + intersection_point_x;
        normal_vector_point2_posy = normal_vector2_y + intersection_point_y;
        Create_Normal_Line_Function(intersection_point_x, intersection_point_y, normal_vector1_x, normal_vector1_y);
        Create_Parallel_Line_Function(original_line_point1_posx, original_line_point1_posy, normal_line_a, normal_line_b);
        intersection_normal_parallel_x = Intersection_X(normal_line_a, normal_line_b, normal_line_c, parallel_line_a, parallel_line_b, parallel_line_c);
        intersection_normal_parallel_y = Intersection_Y(normal_line_a, normal_line_b, normal_line_c, parallel_line_a, parallel_line_b, parallel_line_c);
        reflect_point_x = 2*intersection_normal_parallel_x - original_line_point1_posx;
        reflect_point_y = 2*intersection_normal_parallel_y - original_line_point1_posy;
//        if(is_reflecting)
//            Calculate_Reflect_Point();
//        if(is_reflecting){
//            reflection(original_line_point1_posx, original_line_point1_posy, intersection_point_x, intersection_point_y, normal_vector1_x, normal_vector1_y);
//        }
        repaint();
    }

    public void mouseMoved(MouseEvent e) {
        
    }
    

}
